﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using AMS.DD35.Common;
using AMS.Core.Services;
using AMS.DD35.DbAccess.SqlClient;
using AMS.Core.Data;
using AMS.Core;
using AMS.DD35.DbAccess;
using AMS.DD35.Common.Data;

namespace AMS.DD35.ServiceLib.Services
{
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class DD35MasterService : IDD35MasterService,
        IDependencySetter<ISessionService>, IDependencySetter<ILoginService>,
        IDependencySetter<IRegisterService>, IDependencySetter<ICharacterService>,
        IDependencySetter<IStaticLookupService>
    {
        ISessionService _session;
        ILoginService _login;
        IRegisterService _register;
        ICharacterService _character;
        IStaticLookupService _lookup;

        #region IoC Container Methods
        public ISessionService SessionService
        {
            get { return _session; }
        }

        public void SetDependency(ISessionService concrete)
        {
            _session = concrete;
        }

        public void SetDependency(ILoginService concrete)
        {
            _login = concrete;
        }

        public void SetDependency(IRegisterService concrete)
        {
            _register = concrete;
        }

        public void SetDependency(ICharacterService concrete)
        {
            _character = concrete;
        }

        public void SetDependency(IStaticLookupService concrete)
        {
            _lookup = concrete;
        }
        #endregion

        #region Constructors
        // is this chain the best way to establish concrete dependencies?
        // What about an IoC container?  Can't get IoCC into it unless
        // I make it statically accessible, which is too dangerous

        public DD35MasterService() // WCF requires _a_ default constructor
            : this(new SessionService(),
            new SqlEDMLoginConnector(),
            new SqlEDMRegisterConnector(),
            new SqlEDMCharacterConnector(),
            new SqlEDMStaticLookupConnector())
        { }

        // no longer used; broke, anyway
        public DD35MasterService(IConfiguration configuration)
            : this(new SessionService(),
            new SqlLoginConnector(configuration),
            new SqlRegisterConnector(configuration),
            new SqlCharacterConnector(configuration),
            new SqlStaticLookupConnector(configuration))
        { }

        public DD35MasterService(ISessionService sessionService,
            ILoginConnector loginConnector,
            IRegisterConnector registerConnector,
            ICharacterConnector characterConnector,
            IStaticLookupConnector lookupConnector)
            : this(new LoginService(loginConnector, sessionService),
            new RegisterService(registerConnector),
            new CharacterService(characterConnector, sessionService),
            new StaticLookupService(lookupConnector, sessionService))
        { }

        public DD35MasterService(ILoginService loginService,
            IRegisterService registerService,
            ICharacterService characterService,
            IStaticLookupService lookupService)
        {
            _session = loginService.SessionService;
            _login = loginService;
            _register = registerService;
            _character = characterService;
            _lookup = lookupService;
        } 
        #endregion

        public object AttemptLogin(LoginData loginData)
        {
            return _login.AttemptLogin(loginData);
        }

        public void Logout(object sessionVariable)
        {
            _login.Logout(sessionVariable);
        }

        public void AttemptRegister(RegistrationData registrationData)
        {
            _register.AttemptRegister(registrationData);
        }

        public CharacterData GetCharacterData(long characterID, object sessionVariable)
        {
            // verify session
            if (!_session.IsValidSession(sessionVariable))
                ExceptionHandler.Exception("no valid session found");

            // get character data
            return _character.GetCharacterData(characterID, sessionVariable);
        }

        public IEnumerable<CharacterData> GetCharactersData(object sessionVariable)
        {
            // verify session
            if (!_session.IsValidSession(sessionVariable))
                ExceptionHandler.Exception("no valid session found");

            return _character.GetCharactersData(sessionVariable);
        }

        public void SaveCharacter(CharacterData characterData, object sessionVariable)
        {
            // verify session
            if (!_session.IsValidSession(sessionVariable))
                ExceptionHandler.Exception("no valid session found");

            // get character data
            _character.SaveCharacter(characterData, sessionVariable);
        }

        public Dictionary<int, string> GetRaces()
        {
            return _lookup.GetRaces();
        }

        public Dictionary<int, string> GetDeities()
        {
            return _lookup.GetDeities();
        }

        public Dictionary<int, string> GetFeats()
        {
            return _lookup.GetFeats();
        }

        public Dictionary<int, string> GetSkills()
        {
            return _lookup.GetSkills();
        }

        public Dictionary<string, string> GetClasses()
        {
            return _lookup.GetClasses();
        }

        public Dictionary<long, string> GetCharacters(object sessionVariable)
        {
            // verify session
            if (!_session.IsValidSession(sessionVariable))
                ExceptionHandler.Exception("no valid session found");

            return _lookup.GetCharacters(sessionVariable);
        }
    }
}
